﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection;
using System.Collections;
using System.ComponentModel;
using UniRlv.COL;

namespace UniRlv.Utility
{
    public class EntityHelper
    {
        static public string GetInsertSql<T>(T t)
        {
            return GetInsertSql(t, t.GetType().Name);
        }

        static public string GetInsertSqls<T>(ICollection<T> c)
        {
            if (c!=null && c.Count>0)
            {
                string tbName = typeof(T).Name;
                string sql = "";
                foreach (var item in c)
                {
                    sql += "|";
                    sql += GetInsertSql(item, item.GetType().Name);
                }

                return sql.Substring(1);
            }
            else
            {
                return "";
            }
            
        }

        static public string GetInsertSql<T>(T t, string tbName)
        {
            return GetInsertSql(GetDicData(t), tbName);
        }

        static public string GetInsertSql(Dictionary<string, object> dic, string tbName)
        {
            string strSql = "", sPre = "", sPost = "";


            IDictionaryEnumerator de = dic.GetEnumerator();

            foreach (string item in dic.Keys)
	        {
                if (item.Equals("id", StringComparison.OrdinalIgnoreCase))
                {//ID自增，不用插入
                    continue;
                }

                sPre += ", [" + item + "]";
                sPost += string.Format(", '{0}'", dic[item]);
	        }

            sPost = sPost.Substring(1);
            sPre = sPre.Substring(1);

            strSql = string.Format("insert into [{0}]({1}) values({2})", tbName, sPre, sPost);

            return strSql.ToString();
        }

        public static string GetQuerySql<T>()
        {
            return GetQuerySql<T>(typeof(T).Name);
        }

        public static string GetQuerySql<T>(string tbName)
        {
            PropertyInfo[] pis = typeof(T).GetProperties();
            string sql = "select ";

            if (pis.Length > 0)
            {
                foreach (PropertyInfo pi in pis)
                {
                    if (!pi.CanWrite)
                    {
                        continue;
                    }

                    sql += "[" + pi.Name + "],";
                }

                sql = sql.Substring(0, sql.Length - 1);
                sql += " from [" + tbName + "]";
            }
            else
            {
                sql += "* from [" + tbName + "]";
            }

            return sql;
        }

        public static string GetUpdateSql<T>(T t)
        {
            return GetUpdateSql(t, t.GetType().Name);
        }

        public static string GetUpdateSql(object obj, string tbName)
        {
            Type type = obj.GetType();
            PropertyInfo[] pis = type.GetProperties();
            string id = string.Empty;

            if (pis.Length > 0)
            {
                Dictionary<string, object> dic = new Dictionary<string, object>();
                object val;

                foreach (PropertyInfo pi in pis)
                {
                    if (!pi.CanWrite)
                    {
                        continue;
                    }

                    val = GetValue(obj, pi.Name);

                    if (pi.Name.Equals("id", StringComparison.OrdinalIgnoreCase))
                    {
                        id = val.ToString();
                        continue;//id号不更新
                    }

                    if (val != null)
                    {
                        if (pi.PropertyType == typeof(DateTime))
                        {
                            DateTime dt = Convert.ToDateTime(val);
                            dic.Add(pi.Name, dt.ToString("yyyy-MM-dd HH:mm:ss"));
                        }
                        else
                        {
                            dic.Add(pi.Name, val);
                        }

                    }
                }

                return GetUpdateSql(dic, "id = '" + id + "'", tbName);

            }

            return string.Empty;
        }

        public static string GetUpdateSql(Dictionary<string, object> dataDic, string whereString, string tbName)
        {
            string strSql = "", sPre = "";

            foreach (string item in dataDic.Keys)
            {
                sPre += string.Format(",[{0}]='{1}' ", item, dataDic[item]);
            }

            sPre = sPre.Substring(1);

            strSql = string.Format("update [{0}] set {1}", tbName, sPre);

            return strSql.ToString() + " where " + whereString;
        }

        /// <summary>
        /// 从服务器返回额查询字符串结果中提取实体对象
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="resultString"></param>
        /// <returns></returns>
        static public T GetObjectFromResult<T>(string resultString) where T : new()
        {
            if (!string.IsNullOrEmpty(resultString))
            {
                ResultEntity obj = JsonHelper.FromJson<ResultEntity>(resultString);
                return GetObjectFromResultEntity<T>(obj);
            }
            else
            {
                return new T();
            }

        }

        /// <summary>
        /// 从服务器返回额查询字符串结果中提取实体对象列表
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="resultString"></param>
        /// <returns></returns>
        static public List<T> GetObjectsFromResult<T>(string resultString) where T : new()
        {
            if (!string.IsNullOrEmpty(resultString))
            {
                ResultEntity obj = GetResultEntityFromResult(resultString);

                return GetObjectsFromResultEntity<T>(obj);
                
            }
            else
            {
                return new List<T>();
            }

        }

        /// <summary>
        /// 从通用结果实体对象中提取实体对象列表
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="resultString"></param>
        /// <returns></returns>
        static public List<T> GetObjectsFromResultEntity<T>(ResultEntity re) where T : new()
        {
            if (re.res)
            {
                List<Dictionary<string, string>> lists = JsonHelper.FromJson<List<Dictionary<string, string>>>(re.obj);
                return EntityHelper.GetObjectsFromListDict<T>(lists);
            }
            else
            {
                return new List<T>();
            }


        }

        /// <summary>
        /// 从通用结果实体对象中提取实体对象
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="resultString"></param>
        /// <returns></returns>
        static public T GetObjectFromResultEntity<T>(ResultEntity re) where T : new()
        {
            if (re.res)
            {
                Dictionary<string, string> dic = JsonHelper.FromJson<Dictionary<string, string>>(re.obj);
                return EntityHelper.GetObjectFromDict<T>(dic);
            }
            else
            {
                return new T();
            }


        }

        /// <summary>
        /// 从服务器返回额查询字符串结果中提取通用结果实体对象
        /// </summary>
        /// <param name="resultString"></param>
        /// <returns></returns>
        static public ResultEntity GetResultEntityFromResult(string resultString)
        {
            if (!string.IsNullOrEmpty(resultString))
            {
                return JsonHelper.FromJson<ResultEntity>(resultString);

            }
            else
            {
                return null;
            }

        }


        /// <summary>
        /// 从字典获取对象
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="dict"></param>
        /// <returns></returns>
        static public T GetObjectFromDict<T>(Dictionary<string, string> dict) where T:new()
        {
            T t = new T();
            foreach (string item in dict.Keys)
            {
                SetVal(t, item, dict[item]);
            }

            return t;
        }

        /// <summary>
        /// 从字典列表获取对象列表
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="maps"></param>
        /// <returns></returns>
        static public List<T> GetObjectsFromListDict<T>(List<Dictionary<string, string>> maps) where T:new()
        {
            List<T> li = new List<T>();

            foreach (Dictionary<string, string> item in maps)
            {
                li.Add(GetObjectFromDict<T>(item));
            }

            return li;
        }

        /// <summary>
        /// 从对象获取字典
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="t"></param>
        /// <returns></returns>
        static public Dictionary<string, object> GetDicData<T>(T t)
        {
            PropertyInfo[] pis = t.GetType().GetProperties();
            Dictionary<string, object> dic = new Dictionary<string, object>();

            if (pis.Length > 0)
            {
                object val;

                foreach (PropertyInfo pi in pis)
                {
                    if (!pi.CanWrite)
                    {
                        continue;
                    }

                    val = GetValue(t, pi.Name);

                    if (pi.PropertyType == typeof(DateTime))
                    {
                        dic.Add(pi.Name, ((DateTime)val).ToString("yyyy-MM-dd HH:mm:ss"));
                    }
                    else
                    {
                        dic.Add(pi.Name, val);
                    }
                }

            }

            return dic;
        }

        /// <summary>
        /// 从对象列表哦获取字典列表
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="t"></param>
        /// <returns></returns>
        static public List<Dictionary<string, object>> GetDicDatas<T>(IEnumerable<T> t)
        {
            List<Dictionary<string, object>> li = new List<Dictionary<string, object>>();
            foreach (var item in t)
            {
                li.Add(GetDicData(item));
            }

            return li;
        }

        /// <summary>
        /// 获取属性类型
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="t"></param>
        /// <param name="name"></param>
        /// <returns></returns>
        static public Type GetPropertyType<T>(T t, string name)
        {
            PropertyInfo pi = t.GetType().GetProperty(name, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance);
            return pi == null ? null : pi.PropertyType;

        }

        /// <summary>
        /// 获取属性名称数组
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="t"></param>
        /// <returns>名称数组</returns>
        static public string[] GetPropertyNames<T>(T t)
        {
            PropertyInfo[] pis = t.GetType().GetProperties();
            List<string> names = new List<string>();


            foreach (PropertyInfo pi in pis)
            {
                if (pi.CanWrite)
                {
                    names.Add(pi.Name);
                }
            }


            return names.ToArray();
        }


        static protected object GetValue<T>(T t, string name)
        {
            PropertyInfo pi = t.GetType().GetProperty(name, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance);
            return pi == null ? null : pi.GetValue(t, null);

        }


        static protected void SetVal<T>(T t, string name, object val)
        {
            PropertyInfo pi = t.GetType().GetProperty(name, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance);

            if (pi != null)
            {
                if (Convert.IsDBNull(val) || val == null)
                {
                    pi.SetValue(t, "", null);
                }
                else
                {
                    if (pi.PropertyType == typeof(int) || pi.PropertyType == typeof(int?))
                    {
                        pi.SetValue(t, Convert.ToInt32(val), null);
                    }
                    else if (pi.PropertyType == typeof(double) || pi.PropertyType == typeof(double?))
                    {
                        pi.SetValue(t, Convert.ToDouble(val), null);
                    }
                    else if (pi.PropertyType == typeof(long) || pi.PropertyType == typeof(long?))
                    {
                        pi.SetValue(t, Convert.ToInt64(val), null);
                    }
                    else if (pi.PropertyType == typeof(byte) || pi.PropertyType == typeof(byte?))
                    {
                        pi.SetValue(t, Convert.ToByte(val), null);
                    }
                    else if (pi.PropertyType == typeof(DateTime?) || pi.PropertyType == typeof(DateTime))
                    {
                        try
                        {
                            pi.SetValue(t, Convert.ToDateTime(val), null);
                        }
                        catch (Exception)
                        {
                            pi.SetValue(t, DateTime.Now, null);
                        }
                        
                    }
                    else
                    {
                        pi.SetValue(t, val, null);
                    }
                }

            }

        }

        /// <summary>
        /// 根据对象类型和特性类型获取指定属性的特性
        /// </summary>
        /// <typeparam name="T1">实体类型参数</typeparam>
        /// <typeparam name="T2">特性类型参数</typeparam>
        /// <param name="attr">属性名称</param>
        /// <returns></returns>
        static protected T2 GetAttribute<T1, T2>(string attr)
            where T2 : Attribute
        {
            PropertyInfo pi = typeof(T1).GetProperty(attr, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance);

            if (pi == null)
            {
                return null;
            } 
            else
            {
                object[] objs = pi.GetCustomAttributes(typeof(T2), true);

                if (objs != null && objs.Length>0)
                {
                    return objs[0] as T2;
                } 
                else
                {
                    return null;
                }
            }
            
        }
        /// <summary>
        /// 获取描述特性
        /// </summary>
        /// <typeparam name="T">实体类型</typeparam>
        /// <param name="attr">属性名称</param>
        /// <returns>描述字符串</returns>
        static public string GetDescription<T>(string attr)
        {
            DescriptionAttribute descAttr = GetAttribute<T, DescriptionAttribute>(attr);
            return descAttr == null ? string.Empty : descAttr.Description;
        }

        static public BindingList<T> FromList<T>(IList<T> li)
        {
            return new BindingList<T>(li);
        }
    }
}
